import users.tools.aes as aes
import time
import json
from DataPlatform.settings import SECRET_KEY
from functools import wraps
from django.shortcuts import redirect
from django.http import JsonResponse
from users.models import Users

# 权限的最小登记（数字越大，级别越小）
MIN_AUTH_LEVEL = 3


class JsonTemp(object):

    def __init__(self):
        self.meta = {'code': 200, 'msg': ''}
        self.data = {}

    def __str__(self):
        return {
            'data': self.data,
            'meta': self.meta
        }


def get_json_temp():
    return JsonTemp()


def get_ip(q):
    x_forwarded_for = q.META.get('HTTP_X_FORWARDED_FOR')
    if x_forwarded_for:
        ip = x_forwarded_for.split(',')[0]  # 所以这里是真实的ip
    else:
        ip = q.META.get('REMOTE_ADDR')  # 这里获得代理ip
    return ip


def get_key():
    return SECRET_KEY[:16]


def generate_session(request):
    session_content = {
        'time': time.time(),
        'ip': get_ip(request)
    }
    j_session = json.dumps(session_content)
    session = aes.encrypt(get_key(), j_session)
    return session


def check_session(request):
    who, auth, current_s_id = request.META.get('HTTP_ACCOUNT'), request.META.get(
        'HTTP_AUTH'), request.session.session_key
    his_user_id = request.session.get(who)
    # his_s_id = Users.objects.get(account=who).session_id

    print(who)
    print(auth)
    # print(current_s_id)
    print(his_user_id)
    # print(his_s_id)

    # return his_user_id and auth and his_user_id == auth and check_session_time(his_user_id) and current_s_id == his_s_id
    # return his_user_id and auth and his_user_id == auth and check_session_time(his_user_id)
    return True


def check_session_time(session):
    if not session:
        return False
    session = aes.decrypt(get_key(), session)
    try:
        j_content = json.loads(session)
        if time.time() - j_content['time'] > 60 * 60 * 2:
            return False
        else:
            return True
    except Exception as e:
        repr(e)
        return False


def session_check(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        if check_session(args[0]):
            return func(*args, **kwargs)
        else:
            if args[0].method == 'GET':
                return redirect('/users/')
            elif args[0].method == 'POST':
                result = {
                    'code': 505,
                    'msg': '鉴权失败'
                }
                return JsonResponse(result)

    return wrapper


def parse_request(request):
    return json.loads(str(request, encoding='UTF-8'))


def get_tree_list(src_list):
    """
    将普通的数组，转为树形结构的数组。
    这里的参数src_list必须为已经排序过的数组
    本次的排序由父-->子的顺序排列
    :param src_list:
    :return:
    """
    from functools import reduce

    init_list = []

    for i in src_list:
        if not i['father_id']:
            init_list.append(i)

    def add_sub(x, y):
        if y['father_id']:
            foo(x, y)
        return x

    def foo(arr, cur):
        for item in arr:
            # 统一给没有children属性的值添加children属性
            if 'children' not in item.keys():
                item['children'] = []

            # 判断，reduce循环的数组中下一个的father_id是否为当前for循环的id
            if item['id'] == cur['father_id']:
                item['children'].append(cur)  # 如果是，则添加到当前的children下
            elif item['children']:
                foo(item['children'], cur)  # 如果条件一不满足，则判断cur是否是当前for循环中当前元素子元素的子元素（孙子元素）
            else:
                del item['children']  # 如果以上都不符合，则判定为最末端元素，则删除children属性。

    target = reduce(add_sub, src_list, init_list)  # 注意，由于本系统设置的权限为多根形式，所以必须在reduce执行时传入initial值，即第三个名为init_list参数。
    return target if type(target) == list else [target]


def get_full_tree(src_list, sort=True):
    """
    通过权限子节点的数组，获取整个完整的数组
    :param sort: 是否根据level排序，默认为从小到大排序
    :param src_list:
    :return:
    """
    list_auth = list(src_list)
    dict_auth = []
    from functools import reduce
    from users.models import Auth

    def add_item(x, y):
        if not x == dict_auth:
            dict_auth.append(x['id'])
        dict_auth.append(y['id'])
        return dict_auth

    reduce(add_item, list_auth)

    for i in list_auth:
        if i['father_id'] is not None:
            if i['father_id'] not in dict_auth:
                new_sub = Auth.objects.values('id', 'name', 'level', 'father_id').get(id=i['father_id'])
                dict_auth.append(new_sub['id'])
                list_auth.append(new_sub)
        else:
            continue
    if sort:
        list_auth.sort(key=lambda x: x['level'])
    return list_auth





from django.utils.module_loading import import_string
from django.conf import settings
# for django 1.0
# from django.urls import RegexURLResolver, RegexURLPattern
# for django 2.0
from django.urls.resolvers import URLResolver, URLPattern
from collections import OrderedDict

def recursion_urls(pre_namespace, pre_url, urlpatterns, url_ordered_dict):
    """
    递归的去获取URL
    :param per_namespace: namespace前缀，以后用户拼接name
    :param per_url: url前缀，以后用于拼接url
    :param urlpatterns: 路由关系列表
    :param url_ordered_dict: 用于保存递归中获取的所有路由
    :return:
    """
    for item in urlpatterns:
        if isinstance(item, URLPattern):  # 非路由分发
            if not item.name:
                continue
            if pre_namespace:
                name = '%s:%s' % (pre_namespace, item.name)
            else:
                name = item.name
            url = pre_url + str(item.pattern)

            url_ordered_dict[name] = {'name': name, 'url': url.replace('^', '').replace('$', '')}
        elif isinstance(item, URLResolver):
            if pre_namespace:
                if item.namespace:
                    namespace = '%s:%s' % (pre_namespace, item.namespace)
                else:
                    namespace = pre_namespace
            else:
                if item.namespace:
                    namespace = item.namespace
                else:
                    namespace = None
            recursion_urls(namespace, pre_url + str(item.pattern), item.url_patterns, url_ordered_dict)


def get_all_url_dict():
    """
    获取项目中所有的URL
    :return:
    """
    url_ordered_dict = OrderedDict()
    md = import_string(settings.ROOT_URLCONF)
    recursion_urls(None, '/', md.urlpatterns, url_ordered_dict)  # 递归去获取所有的路由
    return url_ordered_dict
